import java.awt.Color;
import java.awt.Point;
import java.util.ArrayList;

import drawing.AlgebraicLine;
import excaptions.AandBZeroException;

import ownclasses.Eigensolver2x2;
import ownclasses.Eigensolver2x2.*;

import ij.IJ;
import ij.ImagePlus;
import ij.plugin.filter.PlugInFilter;
import ij.process.ByteProcessor;
import ij.process.ImageProcessor;


public class A02_Find_Algebraic_Line implements PlugInFilter{

	public ArrayList<Point> allPoints;
	
	public int setup(String arg, ImagePlus im) {
		return DOES_8G + DOES_RGB + NO_CHANGES;
    }
	
	
	public void run(ImageProcessor ip) {
		allPoints = new ArrayList<Point>();
		//ip.invert();
		//ip.invertLut();
		//Find all Points in Image
		ImageProcessor ip3 = ip.duplicate();
		ImageProcessor ip2 = new ByteProcessor(ip.getWidth(), ip.getHeight());
		ip2 = ip.duplicate().convertToByte(true);
		ip2.invert();
		ip2.invertLut();
		//(new ImagePlus("ip2", ip2)).show();
		
		for(int i = 1; i <= ip2.getHeight()+1; i++)
		{
			for(int j = 1; j <= ip2.getWidth(); j++)
			{
				//IJ.log(" "+ip2.getPixel(j, i));
				if(ip2.getPixel(j, i) > 0)
				{
					allPoints.add(new Point(j, i));
				}
			}
		}
		IJ.log("Punkte: "+allPoints.size());
		
		double x = 0;
		double xx = 0;
		double y = 0;
		double yy = 0;
		double xy = 0;
		for(int i = 0; i < allPoints.size(); i++)
		{
			Point a = allPoints.get(i);
			//IJ.log("X: " + a.getX()+" Y: "+a.getY());
			x += a.getX();
			y += a.getY();
			xx += (a.getX() * a.getX());
			yy += (a.getY() * a.getY());
			xy += (a.getX() * a.getY());
		}
		x = x/allPoints.size();
		y = y/allPoints.size();
		xx = xx/allPoints.size();
		yy = yy/allPoints.size();
		xy = xy/allPoints.size();
		
		double alpha = xx - (x*x);
		double beta = xy-x*y;
		double gamma = yy-(y*y);
		//IJ.log("a: " + alpha + " | " + beta + " | "+gamma);
		EigenPair[] e = Eigensolver2x2.realEigenValues2x2(alpha, beta, beta, gamma);
		double theta = e[1].getEigenvalue();
		double A = e[1].getEigenvector()[0];
		double B = e[1].getEigenvector()[1];
		if(e[0].getEigenvalue() < e[1].getEigenvalue())
		{
			theta = e[0].getEigenvalue();
			A = e[0].getEigenvector()[0];
			B = e[0].getEigenvector()[1];
		} else 
		{
			theta = e[1].getEigenvalue();
			A = e[1].getEigenvector()[0];
			B = e[1].getEigenvector()[1];
		}
		double C = 0 - (x * A) - (y * B);
		//IJ.log("A: " + A+" B: "+B+" C: "+C);
		AlgebraicLine al;
		try {
			al = new AlgebraicLine(A, B, C);
			al.normalize();
			IJ.log("A: " + al.m_A+" B: "+al.m_B+" C: "+al.m_C);
			double sumError = 0.0;
			
			for(int i = 0; i < allPoints.size(); i++)
			{
				sumError += al.distance(allPoints.get(i));
			}
			IJ.log("Sum Error: "+sumError);
			ip3 = al.draw(ip3, Color.red);
		} catch (AandBZeroException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		
		
		(new ImagePlus("Find algebraic line", ip3)).show();
		
		
		//IJ.log("Gefundene Punkte: " + allPoints.size());
		
		
	}

	

}
